#include "scrolltext.h"

ScrollText::ScrollText(QWidget *parent) :
    QWidget(parent)
  ,m_isDragging(false)
  ,m_mouseSrcPos(0)
  ,m_currentIndex(0)
  ,m_deviation(0)
{
    m_homingAni  = new QPropertyAnimation(this, "deviation");
    m_homingAni->setDuration(300);
    m_homingAni->setEasingCurve(QEasingCurve::OutQuad);
}

ScrollText::ScrollText(const QStringList &textList, QWidget *parent) :
    QWidget(parent)
  ,m_isDragging(false)
  ,m_mouseSrcPos(0)
  ,m_currentIndex(0)
  ,m_deviation(0)
{
    m_textList.append(textList);
    m_homingAni  = new QPropertyAnimation(this, "geometry");
    m_homingAni->setDuration(300);
    m_homingAni->setEasingCurve(QEasingCurve::OutQuad);
}

void ScrollText::setScrollTextList(const QStringList &textList)
{
    m_textList.clear();
    m_textList.append(textList);

    m_mouseSrcPos = 0;
    m_currentIndex = 0;
    m_deviation = 0;

    this->repaint();
}

void ScrollText::mousePressEvent(QMouseEvent *event)
{
    if (m_textList.isEmpty())
        return ;

    m_homingAni->stop();
    m_isDragging = true;
    m_mouseSrcPos = event->pos().y();
}

void ScrollText::mouseMoveEvent(QMouseEvent *event)
{
    if (!m_isDragging)
        return ;

    if ( (m_currentIndex == 0 && event->pos().y() >= m_mouseSrcPos) ||
         (m_currentIndex == m_textList.count() - 1 && event->pos().y() <= m_mouseSrcPos))
    {
        return ;
    }

    int pos     = event->pos().y();
    int length  = this->height();

    m_deviation = pos - m_mouseSrcPos;

    //若移动速度过快时进行限制
    if(m_deviation > (length - 1) / 4)
        m_deviation = (length - 1) / 4;
    else if(m_deviation < -(length - 1) / 4)
        m_deviation = -(length - 1) / 4;

    repaint();
}

void ScrollText::mouseReleaseEvent(QMouseEvent *)
{
    if(!m_isDragging)
        return ;
    m_isDragging = false;
    homing();
}

void ScrollText::paintEvent(QPaintEvent *)
{
    if (m_textList.isEmpty())
        return ;

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);

    int measurement = this->height() - 1;
    if(m_deviation >= measurement / 4 && m_currentIndex > 0)
    {
        m_mouseSrcPos   += measurement / 4;
        m_deviation     -= measurement / 4;

        m_currentIndex  -= 1;
    }
    if(m_deviation <= -measurement / 4 && m_currentIndex < m_textList.count()-1)
    {
        m_mouseSrcPos   -= measurement / 4;
        m_deviation     += measurement / 4;
        m_currentIndex  += 1;
    }

    //中间数字
    paintText(painter, m_currentIndex, m_deviation);

    //两侧数字1
    int temp = m_currentIndex - 1;
    if (temp >= 0)
        paintText(painter, temp, m_deviation - measurement / 3);
    temp = m_currentIndex + 1;
    if (temp < m_textList.count())
        paintText(painter, temp, m_deviation + measurement / 3);

    //两侧数字2,超出则不显示
    if(m_deviation >= 0)
    {
        temp = m_currentIndex - 2;
        if (temp >= 0)
            paintText(painter, temp, m_deviation - measurement / 2);
    }
    if(m_deviation <= 0)
    {
        temp = m_currentIndex + 2;
        if (temp < m_textList.count())
            paintText(painter, temp, m_deviation + measurement / 2);
    }
    paintLine(painter);
}

void ScrollText::paintText(QPainter &painter, int index, int deviation)
{
    painter.save();

    int measurement = this->height() - 1;
    int size = (measurement - qAbs(deviation)) / 10;
    //颜色透明度
    int transparency = 255 - 510 * qAbs(deviation) / measurement;
    if (transparency < 0)
        transparency = 0;
    int len = measurement / 2 - 3 * qAbs(deviation) / 4;
    int pos = measurement / 2 + deviation - len / 2;

    QFont font;
    font.setPixelSize(size);
    painter.setFont(font);
    painter.setPen(QColor(254, 0, 254, transparency));

    painter.drawText(QRectF(0, pos, this->height()-1, len), Qt::AlignCenter, m_textList.at(index));

    painter.restore();
}

void ScrollText::paintLine(QPainter &painter)
{
    painter.save();

    QPen pen;
    pen.setBrush(QColor(254, 254, 254, 120));
    pen.setWidth(4);
    pen.setCapStyle(Qt::RoundCap);
    pen.setStyle(Qt::SolidLine);
    painter.setPen(pen);

    int space = 10;
    int up_down_space = this->width() / 10;
    QPoint left_up = QPoint(up_down_space, space + (this->height() - space * 2) / 3);
    QPoint left_down = QPoint(2 * space + (this->width() - space * 2) - up_down_space, space + (height() - space * 2) / 3);
    QPoint right_up = QPoint(up_down_space, space + ((this->height() - space * 2) / 3) * 2);
    QPoint right_down = QPoint(2 * space + (this->width() - space * 2) - up_down_space, space + ((this->height() - space * 2) / 3) * 2);
    painter.drawLine(left_up, left_down);
    painter.drawLine(right_up, right_down);

    painter.restore();
}

void ScrollText::homing()
{
    if(m_deviation > (this->height()) / 20)
    {
        m_homingAni->setStartValue(((this->height()) - 1) / 8 - m_deviation);
        m_homingAni->setEndValue(0);
        if (m_currentIndex > 0)
            m_currentIndex--;
    }
    else if(m_deviation > -(this->height()) / 20)
    {
        m_homingAni->setStartValue(m_deviation);
        m_homingAni->setEndValue(0);
    }
    else if(m_deviation < -(this->height()) / 20)
    {
        m_homingAni->setStartValue(-((this->height()) - 1) / 8 - m_deviation);
        m_homingAni->setEndValue(0);
        if (m_currentIndex < m_textList.count()-1)
            m_currentIndex++;
    }else{
        emit scrollFinishSign();
        return;
    }
    emit scrollFinishSign();
    m_homingAni->start();
}
